{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3210afee",
   "metadata": {},
   "source": [
    "# 初步认知\n",
    "\n",
    "```{admonition} 需求\n",
    "对于 C++ 代码形成初步认知。\n",
    "```\n",
    "\n",
    "```{hint}\n",
    "{guilabel}`视频`\n",
    "\n",
    "- [C++ 的对象、类型、值和变量](https://www.bilibili.com/video/BV1tZ4y1X7Hh)\n",
    "- [C++ 变量命名规则](https://www.bilibili.com/video/BV1uD4y1c7dz)\n",
    "- [C++ 基本类型、简单运算符、类型安全与转换、表达式、赋值语句](https://www.bilibili.com/video/BV1t44y177e8)\n",
    "```\n",
    "\n",
    "\n",
    "信息的最小单位是 {term}`位` （也可称作 比特），一个位仅仅存储 `0` 或者 `1` 两个数字。大多数计算机中的基本寻址单元为 {term}`字节`（1 byte = 8 bit），与一个字符占据的空间大小相当。C++ 对内存做了抽象，将一块内存抽象为一个 {term}`对象`。对象的 {term}`值` 便是其对应的内存空间存储的一组比特值，值所代表的含义和所占据的比特数由其 {term}`类型` 决定。对象需要一个 **名字** 以方便使用，称给定类型的命名对象为 {term}`变量`。{term}`声明` 负责为程序引入一个新的名字，并指定该命名实体的类型。\n",
    "\n",
    "C++ 提供了若干基本类型，例如：\n",
    "\n",
    "- `bool`：布尔类型。可取 `true` 或 `false`。\n",
    "- `char`：字符类型。如 `'a'`，`'\\n'` 等\n",
    "- `int`：整数类型。如 1，42 等\n",
    "- `double`：双精度浮点数类型。如 2.3，5.0\n",
    "\n",
    "这些基本类型都与硬件特性直接相关，其尺寸固定不变，决定了其中所能存储的值的范围。\n",
    "\n",
    "## 标识符\n",
    "\n",
    "**标识符** 是以字母和下划线开头，后接 0 个或者多个（大写或者小写）字母、数字或者下划线的序列。标识符也可以称作 **名字** 或者是 **变量名称**。\n",
    "\n",
    "想要使用一个变量，需要使用 {term}`声明`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "60037753",
   "metadata": {},
   "outputs": [],
   "source": [
    "int 苹果数量;"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca47b77b",
   "metadata": {},
   "source": [
    "其中 `苹果数量` 便是一个变量；`int` 便是一个类型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4a1971da",
   "metadata": {},
   "outputs": [],
   "source": [
    "int hi_world;\n",
    "int HiWorld;"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "e014c21a",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_9:2:8: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mexpected ';' at end of declaration\u001b[0m\n",
      " int Hi World; // 错误：因为标识符不能有空格\n",
      "\u001b[0;1;32m       ^\n",
      "\u001b[0m\u001b[0;32m       ;\n",
      "\u001b[0m"
     ]
    },
    {
     "ename": "Interpreter Error",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Interpreter Error: "
     ]
    }
   ],
   "source": [
    "int Hi World; // 错误：因为标识符不能有空格"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52aee777",
   "metadata": {},
   "source": [
    "```{note}\n",
    "C++ 使用符号 `//` 注解代码片段，以帮助人们理解。编译器不会编译注解内容。\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "cc2fb456",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_10:2:8: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mexpected ';' at end of declaration\u001b[0m\n",
      " int Hi@World; // 错误：因为标识符不能有 @\n",
      "\u001b[0;1;32m       ^\n",
      "\u001b[0m\u001b[0;32m       ;\n",
      "\u001b[0m"
     ]
    },
    {
     "ename": "Interpreter Error",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Interpreter Error: "
     ]
    }
   ],
   "source": [
    "int Hi@World; // 错误：因为标识符不能有 @"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b36239dd",
   "metadata": {},
   "source": [
    "### 双下划线\n",
    "\n",
    "以下划线开头或者包含连续两个下划线的标识符是为 C++ 实现预留的，你的程序中不要使用这种标识符。例如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8a52f636",
   "metadata": {},
   "outputs": [],
   "source": [
    "int _foo; // 不要这样用\n",
    "int foo_boor; // 正确\n",
    "int foo__bar; // 不要这样用\n",
    "int foo_; // 正确"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "011a01c3",
   "metadata": {},
   "source": [
    "### 关键字\n",
    "\n",
    "**关键字** 是 C++ 用来表示语言结构的特殊标识符。比如，类型 `int` 便是关键字。\n",
    "\n",
    "## 基本运算符\n",
    "\n",
    "运算符可以用于操作对象以实现某些功能。下面仅仅介绍一些基本运算符：\n",
    "\n",
    "算术运算符\n",
    ":   ```c++\n",
    "    x+y   // 加法\n",
    "    +x   // 一元加法\n",
    "    x-y  // 减法\n",
    "    -x   // 一元减法\n",
    "    x*y  // 乘法\n",
    "    x/y  // 除法\n",
    "    x%y  // 取模（x，y 不能是浮点数类型）\n",
    "    ```\n",
    "\n",
    "比较运算符\n",
    ":   ```c++\n",
    "    x==y   // 相等\n",
    "    x!=y  // 不相等\n",
    "    x<y  // 小于\n",
    "    x>y  // 大于\n",
    "    x<=y  // 小于等于\n",
    "    x>=y  // 大于等于\n",
    "    ```\n",
    "\n",
    "赋值运算符\n",
    ":   `=`\n",
    "\n",
    "    为一个变量赋予新的值。\n",
    "    \n",
    "\n",
    "### 运算符 `sizeof`\n",
    "\n",
    "可以使用运算符 `sizeof` 获取类型的对象大小。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "71d29f55",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sizeof(bool) // 1 个字节"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a2169c84",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sizeof(char) // 1 个字节"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "8c84e41e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sizeof(int) //  4 个字节"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6fbd4913",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sizeof(double)  // 8 个字节"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0102be60",
   "metadata": {},
   "source": [
    "## 初始化\n",
    "\n",
    "通用初始化方法是使用花括号内的一组初始化器列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6be1f52c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.3000000"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "double d1 {2.3};\n",
    "d1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe4c0f6c",
   "metadata": {},
   "source": [
    "当然也可以使用传统的方法，即赋值语句："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "44bba3c8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.3000000"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "double d1 = 2.3;\n",
    "d1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "add80bc3",
   "metadata": {},
   "source": [
    "## 赋值语句\n",
    "\n",
    "看几个赋值语句的例子："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d1a4ee2f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int a = 7; // a 初始化为 7\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "a56542ab",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 4; // a 通过 赋值语句，获得新值 4\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b1134142",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int b = a; // b 的值为 a 的值的拷贝\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "716d83cd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = a + 5; // b 获得新值 a+5\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "b70afafa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = a + 7; // a 获得新值 a+7\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9078a397",
   "metadata": {},
   "source": [
    "### 复合赋值运算符\n",
    "\n",
    "一个变量的递加（增加 1），可以简写为 `++vars`。比如："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "3f578af2",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int a = 7;\n",
    "a // 查看 a 的值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "315edfb1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "++a; // 等同于 `a = a + 1;`\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "8ad9537f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "--a; // 等同于 `a = a - 1;`\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03733a26",
   "metadata": {},
   "source": [
    "一些二元赋值运算符，可以直接修改变量的当前值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "15340d1b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int a = 7;\n",
    "a += 7; // 表示 `a = a + 7;`\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0fffbf8e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a -= 7; // 表示 `a = a - 7;`\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "0886bd22",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a *= 2; // 表示 `a = a * 2;`\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "0e60979f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a /= 2; // 表示 `a = a / 2;`\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "9ab96b89",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a %= 2; // 表示 `a = a % 2;`\n",
    "a"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c42dfc7",
   "metadata": {},
   "source": [
    "在很多领域 `*=` 和 `/=` 被视为“缩放”。\n",
    "\n",
    "## 表达式\n",
    "\n",
    "表达式是从一些 {term}`操作数` 计算一个值。最简单的表达式是字面常量，例如：`10`、`'a'`、`3.14`、`\"喜爱\"`。\n",
    "\n",
    "变量也是一种表达式，它表示与名字对应的那个对象。同样赋值语句也是表达式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "21159279",
   "metadata": {},
   "outputs": [],
   "source": [
    "// 计算一些表达式\n",
    "int 长度 = 30; // 整数字面常量（用于变量的初始化）\n",
    "int 宽度 = 50;\n",
    "int 面积 = 长度 * 宽度; // 乘法运算"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd4d3e7e",
   "metadata": {},
   "source": [
    "```{note}\n",
    "- 字面常量 `30` 和 `50` 用于初始化变量 `长度` 和 `宽度`；\n",
    "- `长度` 和 `宽度` 进行乘法运算，此时可以将它们理解为变量的值进行乘法运算。\n",
    "```\n",
    "\n",
    "```{important}\n",
    "名字在赋值号左边称为 **左值**，名字在赋值号右边称为 **右值**。\n",
    "```\n",
    "\n",
    "赋值语句 `int 长度 = 30;`，`=` 左边的名字其含义是名字为 `长度` 的变量，此赋值语句的含义是“把 `30` 赋值给名为 `长度` 的变量”；赋值语句 `int 面积 = 长度 * 宽度;` 右边的名字 `长度` 表示这个变量的值。\n",
    "\n",
    "`sizeof` 也可以计算表达式的 **结果对象** 的大小。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "ff750021",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float x = 56;\n",
    "sizeof(x*5+10) // 计算的是 x*5+10 的结果 290.0 的大小"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30f2c43f",
   "metadata": {},
   "source": [
    "```{note}\n",
    "`x % y` 表达式中的 `x` 与 `y` 不能是浮点型。\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "e2e5c3ca",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_55:4:3: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1minvalid operands to binary expression ('double' and 'double')\u001b[0m\n",
      "x % y\n",
      "\u001b[0;1;32m~ ^ ~\n",
      "\u001b[0m"
     ]
    },
    {
     "ename": "Interpreter Error",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Interpreter Error: "
     ]
    }
   ],
   "source": [
    "double x {45};\n",
    "double y {7};\n",
    "x % y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "5f966982",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_56:4:3: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1minvalid operands to binary expression ('double' and 'double')\u001b[0m\n",
      "x % y\n",
      "\u001b[0;1;32m~ ^ ~\n",
      "\u001b[0m"
     ]
    },
    {
     "ename": "Interpreter Error",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Interpreter Error: "
     ]
    }
   ],
   "source": [
    "double x {45};\n",
    "int y {7};\n",
    "x % y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "b7fa84de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int x {45};\n",
    "int y {7};\n",
    "x % y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd50a580",
   "metadata": {},
   "source": [
    "对于比较运算符 `==` 避免出现歧义，单独使用时，请使用 `()` 括起来。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "8614959c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_61:2:4: \u001b[0m\u001b[0;1;30mnote: \u001b[0muse '=' to turn this equality comparison into an assignment\u001b[0m\n",
      " x == y; // 这种写法有歧义\n",
      "\u001b[0;1;32m   ^~\n",
      "\u001b[0m\u001b[0;32m   =\n",
      "\u001b[0m"
     ]
    },
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x == y; // 这种写法有歧义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "34231400",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "false"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "(x == y); // 这样才是正确的写法"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d89dbf61",
   "metadata": {},
   "source": [
    "## 类型安全\n",
    "\n",
    "对于一个程序或者程序的一部分，若使用的对象符合它们的规定，则它们是类型安全的。\n",
    "\n",
    "下面列出一些不是类型安全的程序："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "573e8477",
   "metadata": {},
   "outputs": [],
   "source": [
    "double xxx; // 仅仅声明，没有初始化，是未定义的\n",
    "double y = xxx; // y 的值也是未定义的\n",
    "double z = 2.0 + xxx; // + 的意义和 z 都是未定义的"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e9d7b79",
   "metadata": {},
   "source": [
    "```{admonition} 建议\n",
    "永远记住初始化你的变量，是一个好习惯！\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0ba8c57",
   "metadata": {},
   "source": [
    "### 安全转换\n",
    "\n",
    "C++ 提供了显式的类型转换："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "895e6a20",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char c = '!';\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "b46b535e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "33"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int t = c; // 安全转换为 int\n",
    "t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "8efe07ab",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "33"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int t2 = '!';\n",
    "t2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "479c842a",
   "metadata": {},
   "source": [
    "这里 `t` 与 `t2` 都被赋值 `33`。我们称这种 char-int 的转换为安全的，这是因为没有信息丢失；同样，可以将 `int` 的结果拷贝会一个 `char` 中，并且得到原始值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "4e8e99b5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'!'"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char c2 = t;\n",
    "c2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82d4142f",
   "metadata": {},
   "source": [
    "### 不安全转换\n",
    "\n",
    "不安全指的是一个值可以转换为一个不等于原始值的值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "0728878e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "525"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int a = 525;\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "bb90ff43",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\r'"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "char c = a; // 试图将一个“大”的整数“压缩”进小的字符型\n",
    "c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "9defb39f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "13"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int b = c;\n",
    "b"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "521d168b",
   "metadata": {},
   "source": [
    "可以看出 `a` 不等于 `b`。\n",
    "\n",
    "这种转换又称为“窄化”转换。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8074fe7c",
   "metadata": {},
   "source": [
    "## 类型转换\n",
    "\n",
    "赋值运算、算术运算以及初始化会在基本类型间进行有意义的类型转换。\n",
    "\n",
    "```{important}\n",
    "若算术表达式中有 `double` 类型数据，则进行浮点型算术运算，结果为 `double` 类型；否则就使用整型算术运算，结果为 `int` 类型。\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "560f9552",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "5/2 // 整型算术运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "fa19db32",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.2500000"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2.5/2 //  浮点型算术运算"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07dd1206",
   "metadata": {},
   "source": [
    "```{important}\n",
    "记号 `type(value)` 和 `type{value}` 表示“将 `value` 转换为 `type` 类型，就像用值 `value` 初始化 `type` 类型的变量一样。”\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "f8bf619f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "98"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'a' + 1; // 等同于 int{'a'} + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "5ecbc9fc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.5000000"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "double d = 2.5; // 初始化浮点数\n",
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "04271839",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int t = 2; // 初始化整数\n",
    "t"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "1d94c80e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.2500000"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "double d2 = d / t;\n",
    "d2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "76939829",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int t2 = d / t; // 窄化转换\n",
    "t2 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39f16ca4",
   "metadata": {},
   "source": [
    "`d / t` 是一个 `double` 值，而 `t2` 是 `int`，所以最终的结果被截断为整数。\n",
    "\n",
    "```{important}\n",
    "使用 `type{value}` 可以避免窄化转换，而 `type(value)` 不能。\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "fbbd55d9",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1minput_line_94:2:10: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mtype 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]\u001b[0m\n",
      " int t3 {d / t};\n",
      "\u001b[0;1;32m         ^~~~~\n",
      "\u001b[0m\u001b[1minput_line_94:2:10: \u001b[0m\u001b[0;1;30mnote: \u001b[0minsert an explicit cast to silence this issue\u001b[0m\n",
      " int t3 {d / t};\n",
      "\u001b[0;1;32m         ^~~~~\n",
      "\u001b[0m\u001b[0;32m         static_cast<int>( )\n",
      "\u001b[0m"
     ]
    },
    {
     "ename": "Interpreter Error",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Interpreter Error: "
     ]
    }
   ],
   "source": [
    "int t3 {d / t};"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7bbe4f2b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++11",
   "language": "C++11",
   "name": "python3100jvsc74a57bd0a2954483fe4136a94bd721da8601251ae4c667fedb6adcfe70ff0183b19bacbc"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "C++11",
   "version": "11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
